// 📁 service/impl/NotificationServiceImpl.java
package com.library.management.service.impl;

import com.library.management.entity.Notification;
import com.library.management.entity.User;
import com.library.management.enums.NotificationPriority;
import com.library.management.enums.NotificationType;
import com.library.management.repository.NotificationRepository;
import com.library.management.repository.UserRepository;
import com.library.management.service.NotificationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
/**
 * 通知服务实现类
 * 处理通知消息相关的业务逻辑实现
 */
@Service
@Transactional
@RequiredArgsConstructor
@Slf4j
public class NotificationServiceImpl implements NotificationService {

    private final NotificationRepository notificationRepository;
    private final UserRepository userRepository;

    @Override
    public Notification save(Notification notification) {
        log.info("保存通知: {}", notification.getTitle());
        return notificationRepository.save(notification);
    }

    @Override
    public Notification update(Long id, Notification notification) {
        log.info("更新通知: {}", id);

        Notification existingNotification = notificationRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("通知不存在: " + id));

        // 更新允许修改的字段
        existingNotification.setTitle(notification.getTitle());
        existingNotification.setContent(notification.getContent());
        existingNotification.setType(notification.getType());
        existingNotification.setPriority(notification.getPriority());
        existingNotification.setIsRead(notification.getIsRead());
        existingNotification.setExpireTime(notification.getExpireTime());

        return notificationRepository.save(existingNotification);
    }

    @Override
    public void delete(Long id) {
        log.info("删除通知: {}", id);
        notificationRepository.deleteById(id);
    }


    @Override
    public Optional<Notification> findById(Long id) {
        return notificationRepository.findById(id);
    }

    @Override
    public Notification getById(Long id) {
        return notificationRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("通知不存在: " + id));
    }
    @Override
    public List<Notification> findAll() {
        return notificationRepository.findAll();
    }

    @Override
    public Page<Notification> findAll(Pageable pageable) {
        return notificationRepository.findAll(pageable);
    }

    @Override
    public boolean exists(Long id) {
        return notificationRepository.existsById(id);
    }

    @Override
    public List<Notification> findByUser(User user) {
        return notificationRepository.findByUser(user);
    }

    @Override
    public List<Notification> findByUserId(Long userId) {
        return notificationRepository.findByUserId(userId);
    }

    @Override
    public List<Notification> findByIsRead(Boolean isRead) {
        return notificationRepository.findByIsRead(isRead);
    }

    @Override
    public List<Notification> findUnreadNotifications() {
        return notificationRepository.findByIsReadFalse();
    }

    @Override
    public List<Notification> findUnreadNotificationsByUserId(Long userId) {
        return notificationRepository.findByUserIdAndIsReadFalse(userId);
    }

    @Override
    public List<Notification> findByType(NotificationType type) {
        return notificationRepository.findByType(type);
    }

    @Override
    public List<Notification> findByPriority(NotificationPriority priority) {
        return notificationRepository.findByPriority(priority);
    }

    @Override
    public List<Notification> findValidNotifications() {
        return notificationRepository.findValidNotifications(LocalDateTime.now());
    }

    @Override
    public List<Notification> findExpiredNotifications() {
        return notificationRepository.findExpiredNotifications(LocalDateTime.now());
    }

    @Override
    public List<Notification> findUrgentNotifications() {
        return notificationRepository.findUrgentNotifications(LocalDateTime.now());
    }

    @Override
    public long countUnreadByUserId(Long userId) {
        return notificationRepository.countByUserIdAndIsReadFalse(userId);
    }

    @Override
    public Notification markAsRead(Long notificationId) {
        log.info("标记通知为已读: {}", notificationId);

        Notification notification = notificationRepository.findById(notificationId)
                .orElseThrow(() -> new RuntimeException("通知不存在: " + notificationId));

        notification.markAsRead();
        return notificationRepository.save(notification);
    }

    @Override
    public void markMultipleAsRead(List<Long> notificationIds) {
        log.info("批量标记通知为已读: {} 个通知", notificationIds.size());
        notificationRepository.markMultipleAsRead(notificationIds, LocalDateTime.now());
    }

    @Override
    public void markAllAsReadByUserId(Long userId) {
        log.info("标记用户所有通知为已读: {}", userId);

        List<Notification> unreadNotifications = findUnreadNotificationsByUserId(userId);
        List<Long> notificationIds = unreadNotifications.stream()
                .map(Notification::getId)
                .toList();

        if (!notificationIds.isEmpty()) {
            markMultipleAsRead(notificationIds);
        }
    }

    @Override
    public Notification sendSystemNotification(User user, String title, String content,
                                               NotificationPriority priority, LocalDateTime expireTime) {
        log.info("发送系统通知给用户: {}, 标题: {}", user.getUsername(), title);

        Notification notification = new Notification();
        notification.setUser(user);
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(NotificationType.SYSTEM);
        notification.setPriority(priority != null ? priority : NotificationPriority.NORMAL);
        notification.setIsRead(false);
        notification.setExpireTime(expireTime);

        return notificationRepository.save(notification);
    }

    @Override
    public Notification sendBorrowNotification(User user, String title, String content,
                                               Long relatedId, LocalDateTime expireTime) {
        log.info("发送借阅通知给用户: {}, 标题: {}", user.getUsername(), title);

        Notification notification = new Notification();
        notification.setUser(user);
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(NotificationType.BORROW);
        notification.setPriority(NotificationPriority.NORMAL);
        notification.setIsRead(false);
        notification.setRelatedId(relatedId);
        notification.setRelatedType("BORROW_RECORD");
        notification.setExpireTime(expireTime);

        return notificationRepository.save(notification);
    }

    @Override
    public Notification sendReturnNotification(User user, String title, String content,
                                               Long relatedId, LocalDateTime expireTime) {
        log.info("发送归还通知给用户: {}, 标题: {}", user.getUsername(), title);

        Notification notification = new Notification();
        notification.setUser(user);
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(NotificationType.RETURN);
        notification.setPriority(NotificationPriority.NORMAL);
        notification.setIsRead(false);
        notification.setRelatedId(relatedId);
        notification.setRelatedType("BORROW_RECORD");
        notification.setExpireTime(expireTime);

        return notificationRepository.save(notification);
    }

    @Override
    public Notification sendOverdueNotification(User user, String title, String content,
                                                Long relatedId, LocalDateTime expireTime) {
        log.info("发送逾期通知给用户: {}, 标题: {}", user.getUsername(), title);

        Notification notification = new Notification();
        notification.setUser(user);
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(NotificationType.OVERDUE);
        notification.setPriority(NotificationPriority.HIGH);
        notification.setIsRead(false);
        notification.setRelatedId(relatedId);
        notification.setRelatedType("BORROW_RECORD");
        notification.setExpireTime(expireTime);

        return notificationRepository.save(notification);
    }

    @Override
    public Notification sendReservationNotification(User user, String title, String content,
                                                    Long relatedId, LocalDateTime expireTime) {
        log.info("发送预约通知给用户: {}, 标题: {}", user.getUsername(), title);

        Notification notification = new Notification();
        notification.setUser(user);
        notification.setTitle(title);
        notification.setContent(content);
        notification.setType(NotificationType.RESERVATION);
        notification.setPriority(NotificationPriority.NORMAL);
        notification.setIsRead(false);
        notification.setRelatedId(relatedId);
        notification.setRelatedType("RESERVATION");
        notification.setExpireTime(expireTime);

        return notificationRepository.save(notification);
    }

    @Override
    public List<Notification> sendBatchNotifications(List<User> users, String title, String content,
                                                     NotificationType type, NotificationPriority priority,
                                                     LocalDateTime expireTime) {
        log.info("批量发送通知给 {} 个用户, 标题: {}", users.size(), title);

        return users.stream()
                .map(user -> {
                    Notification notification = new Notification();
                    notification.setUser(user);
                    notification.setTitle(title);
                    notification.setContent(content);
                    notification.setType(type);
                    notification.setPriority(priority != null ? priority : NotificationPriority.NORMAL);
                    notification.setIsRead(false);
                    notification.setExpireTime(expireTime);
                    return notification;
                })
                .map(notificationRepository::save)
                .toList();
    }

    @Override
    public void deleteExpiredNotifications() {
        log.info("删除过期通知");
        notificationRepository.deleteExpiredNotifications(LocalDateTime.now());
    }

    @Override
    public Page<Notification> findByUserId(Long userId, Pageable pageable) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在: " + userId));
        return notificationRepository.findByUser(user, pageable);
    }

    @Override
    public Page<Notification> findUnreadByUserId(Long userId, Pageable pageable) {
        return notificationRepository.findByUserIdAndIsReadFalse(userId, pageable);
    }

    @Override
    public List<Notification> findByRelatedInfo(Long relatedId, String relatedType) {
        return notificationRepository.findByRelatedIdAndRelatedType(relatedId, relatedType);
    }
}